﻿using System;
using System.Runtime.InteropServices;
using System.Threading;
using OpenCvSharp;

//这两种好像都支持
public delegate void Callback(IntPtr handle, IntPtr data, int len, int w, int h, int type);
//public delegate void Callback(IntPtr handle, byte[] data, int len, int w, int h, int type);

namespace rtsp_player_CSharp
{
    class Program
    {
        const string LIBRTSP = "librtsp.dll"; // Update with the actual name of the C library

        [DllImport(LIBRTSP)]
        public static extern void rtsp_enable_console_log();

        [DllImport(LIBRTSP)]
        public static extern void rtsp_pixel_format(int type);

        [DllImport(LIBRTSP)]
        public static extern void rtsp_init();

        [DllImport(LIBRTSP)]
        public static extern void rtsp_uninit();

        [DllImport(LIBRTSP)]
        //测试这两种声明传uri都成功了

        //public static extern IntPtr rtsp_generate([MarshalAs(UnmanagedType.LPStr)] string uri,Callback pFunDecodeData);
        public static extern IntPtr rtsp_generate(string uri, Callback pFunDecodeData);

        [DllImport(LIBRTSP)]
        public static extern int rtsp_release(ref IntPtr handle);

        [DllImport(LIBRTSP)]
        public static extern int rtsp_start(IntPtr handle);

        [DllImport(LIBRTSP)]
        public static extern int rtsp_stop(IntPtr handle);

        //这里传入一个IntPtr去取 无需分配内存
        [DllImport(LIBRTSP)]
        public static extern int rtsp_getframe(IntPtr handle, out IntPtr data, out int len, out int w, out int h, out int type);

        //这里预分配足够大的byte[] data 去取
        [DllImport(LIBRTSP)]
        public static extern int rtsp_getframe_ex(IntPtr handle, byte[] data, out int len, out int w, out int h, out int type);

        static Callback callback = (IntPtr handle, IntPtr pData, int len, int w, int h, int type) =>
        {
            return;
            //被动回调解码数据的方式
            byte[] frameData = new byte[len];
            Marshal.Copy(pData, frameData, 0, len);
            Mat mat = new Mat(h, w, MatType.CV_8UC3, frameData);
            Cv2.CvtColor(mat, mat, ColorConversionCodes.RGB2BGR);
            Cv2.ImShow("callback", mat);
            Cv2.WaitKey(1);
        };

        static void Main(string[] args)
        {
            string url = "rtsp://admin:able1234@192.168.50.249/stream1";
            rtsp_init();
            rtsp_enable_console_log();
            IntPtr handle =  rtsp_generate(url,null);          
            rtsp_start(handle);

            bool Flag = true;

            Thread thread = new Thread(() =>
            {
                while (Flag)
                {                       
                    int len, w, h, type,result;

                    IntPtr dataPtr;
                    result = rtsp_getframe(handle, out dataPtr, out len, out w, out h, out type);
                    if (result == 0)
                    {
                        //拷贝走
                        //byte[] frameData = new byte[len];
                        //Marshal.Copy(dataPtr, frameData, 0, len);
                        //Mat mat = new Mat(h, w, MatType.CV_8UC3, frameData);
                        //Cv2.CvtColor(mat, mat, ColorConversionCodes.RGB2BGR);
                        //Cv2.ImShow("rtsp_getframe", mat);
                        //Cv2.WaitKey(1);
                        //frameData = null;
                    }
                    else
                    {
                        //Console.WriteLine($"Failed to get frame from RTSP stream result={result}");
                    }
                    Thread.Sleep(1);
                }
            });

            // 启动线程
            thread.Start();


            while (true)
            {
                ConsoleKeyInfo keyInfo = Console.ReadKey(true);
                if (keyInfo.KeyChar == 'q' || keyInfo.KeyChar == 'Q')
                {
                    Flag = false;
                    if (thread.IsAlive)
                    {
                        thread.Join();
                    }         
                    break;
                }
            }
            rtsp_stop(handle);
            rtsp_release(ref handle);
            Console.WriteLine($"release result:{handle == IntPtr.Zero}");
            rtsp_uninit();
            ConsoleKeyInfo b = Console.ReadKey(true);
        }
    }
}
